home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
COMM
/
PPL4P10A
/
AMODEM.PAS
next >
Wrap
Pascal/Delphi Source File
|
1995-02-20
|
10KB
|
343 lines
(*********************************************)
(* *)
(* --- ASCII Protocol --- *)
(* *)
(* This program is donated to the Public *)
(* Domain by MarshallSoft Computing, Inc. *)
(* It is provided as an example of the use *)
(* of the Personal Communications Library. *)
(* *)
(*********************************************)
{ $DEFINE DEBUG}
{$I DEFINES.PAS}
unit amodem;
interface
uses term_io,PCL4P,crt,xypacket,file_io;
(* reference 'file_io' to get BufferType definition *)
function TxAscii(
Port : Integer; (* COM port [0..3] *)
Var Filename : String; (* filename buffer *)
CharPace : Integer; (* delay between characters (timer tics) *)
TermChar : Byte; (* termination character ($00 => none) *)
TimeOut : Integer; (* delay after which assume sender is done (secs) *)
EchoFlag : Boolean) (* local echo flag *)
: Boolean;
function RxAscii(
Port : Integer; (* COM port [0..3] *)
Var Filename : String; (* filename buffer *)
TermChar : Byte; (* termination character ($00 => none) *)
TimeOut : Integer; (* delay after which assume sender is done (secs) *)
EchoFlag : Boolean) (* local echo flag *)
: Boolean;
implementation
Const
XON = $11;
XOFF = $13;
CAN = $18;
ESC = $1B;
ONE_SECOND = 18;
Var (* globals *)
LastXchar : Byte; (* last XON or XOFF *)
LastTime : LongInt; (* last time character was received *)
DataCount : Integer; (* # bytes in Buffer *)
TheTermChar : Byte;
Procedure DiskError;
Begin
WriteMsg('Disk I/O Error');
fioClose
End;
procedure ReportBytes(Bytes : LongInt);
var
Message : String[50];
begin
Str(Bytes,Message);
Message := 'Ascii: ' + Message + ' bytes.';
WriteMsg(Message);
end;
function UserQuits(Port : Integer) : Boolean;
var
UserChar : Char;
Code : Integer;
begin
(* does user want to quit ? *)
UserQuits := FALSE;
if KeyPressed then
begin
UserChar := ReadKey;
if Ord(UserChar) = CAN then
begin
TxCAN(Port);
Code := SioPutc(Port,chr(TheTermChar));
WriteMsg('Ascii: Aborted by USER...');
UserQuits := TRUE
end
else Code := SioPutc(Port,UserChar);
end
end;
function CheckForXOFF(Port:Integer) : Boolean;
Var
Code : Integer;
begin
(* check for incoming XOFF *)
Code := GetChar(Port,0);
if Code = XOFF then
begin
(* received a XOFF *)
WriteMsg('Ascii: XOFF received');
LastXchar := XOFF;
CheckForXOFF := TRUE;
end
else CheckForXOFF := FALSE
end;
function WaitForXON(Port:Integer;TimeOut:Integer) : Boolean;
Var
Code : Integer;
ExitFlag : Boolean;
begin
LastTime := SioTimer;
ExitFlag := FALSE;
repeat
Code := GetChar(Port,ONE_SECOND);
if Code = -1 then
begin
(* nothing there *)
if SioTimer-LastTime > 60*ONE_SECOND then
begin
(* we have timed out *)
WriteMsg('Ascii: Timed out waiting for XON');
WaitForXON := FALSE;
ExitFlag := TRUE;
end
end
else
(* character received *)
begin
if Code = XON then
begin
(* received character was XON *)
WriteMsg('Ascii: XON received');
LastXchar := XON;
WaitForXON := TRUE;
ExitFlag := TRUE;
end
else
begin
(* received character wasn't a XON *)
WriteMsg('Ascii: Received character not XON');
end
end
until ExitFlag;
end;
procedure CheckQueue(Port,LoMark,HiMark:Integer);
var
QueueSize : Integer;
begin
QueueSize := SioRxQue(Port);
if (QueueSize>HiMark) and (LastXchar=XON) then
begin
PutChar(Port,XOFF);
LastXchar := XOFF;
WriteMsg('Ascii: Sending XOFF')
end;
if (QueueSize<LoMark) and (LastXchar=XOFF) then
begin
PutChar(Port,XON);
LastXchar := XON;
WriteMsg('Ascii: Sending XON')
end
end;
function TxAscii(
Port : Integer; (* COM port [0..3] *)
Var Filename : String; (* filename buffer *)
CharPace : Integer; (* millisecond delay between characters *)
TermChar : Byte; (* termination character ($00 => none) *)
TimeOut : Integer; (* delay after which assume sender is done *)
EchoFlag : Boolean) (* local echo flag *)
: Boolean;
Var
Buffer : BufferType;
i : Integer;
Code : Integer;
c : Char;
TheByte : Byte;
BytesRead : Word;
ExitFlag : Boolean;
TxChars : LongInt;
Message : String[50];
begin
TheTermChar := TermChar;
if not fioOpen(Filename) then
begin
Message := 'Ascii: Cannot open ' + Filename;
WriteMsg(Message);
TxAscii := FALSE;
exit;
end;
(* start ascii send *)
WriteMsg('Ascii: Starting SEND');
LastXchar := XON;
ExitFlag := FALSE;
TxChars := 0;
(* flush keyboard & serial port *)
while KeyPressed do c := ReadKey;
Code := SioRxFlush(Port);
(* send ascii file *)
repeat
(* does user want to quit ? *)
if UserQuits(Port) then exit;
(* read next buffer from disk *)
if not fioRead(Buffer,1024,BytesRead) then
begin
DiskError;
TxAscii := False;
exit
end;
(* send 1 character at a time *)
for i := 0 to BytesRead-1 do
begin
(* send character & delay *)
TheByte := Buffer[i];
PutChar(Port,TheByte);
if EchoFlag then write(chr(TheByte));
if CharPace > 0 then SioDelay(CharPace);
if TheByte = $0d then SioDelay(5);
TxChars := TxChars + 1;
if (TxChars mod 100) = 0 then ReportBytes(TxChars);
(* check for incoming XOFF *)
if CheckForXOFF(Port) then
begin
(* received XOFF, so wait for XON *)
if not WaitForXON(Port,TimeOut) then ExitFlag := TRUE;
end
end;
until ExitFlag or (BytesRead = 0);
(* send termination character, if any *)
if TermChar <> $00 then
begin
PutChar(Port,TermChar);
WriteMsg('Ascii: Termination character sent');
end;
fioClose;
TxAscii := True
end; (* TxAscii *)
function RxAscii(
Port : Integer; (* COM port [0..3] *)
Var Filename : String; (* filename buffer *)
TermChar : Byte; (* termination character ($00 => none) *)
TimeOut : Integer; (* delay after which assume sender is done *)
EchoFlag : Boolean) (* local echo flag *)
: Boolean;
Const
RxBufSize = 1024;
Var
Buffer : BufferType;
c : Char;
i, k : Integer;
Code : Integer; (* return code *)
Flag : Boolean;
Message : String;
Temp : String;
Result : Integer;
LoMark : Integer; (* receive buffer low water mark *)
HiMark : Integer; (* receive buffer high water mark *)
ExitFlag : Boolean;
RxChars : LongInt;
(* begin *)
begin
TheTermChar := TermChar;
if not fioCreate(Filename) then
begin
Message := 'Ascii: Cannot open ' + Filename;
WriteMsg(Message);
RxAscii := FALSE;
exit
end;
(* flush keyboard & serial port *)
while KeyPressed do c := ReadKey;
Code := SioRxFlush(Port);
(* receive text *)
WriteMsg('Ascii: Starting RECEIVE');
LoMark := RxBufSize div 8;
HiMark := 5 * LoMark;
LastXchar := XON;
DataCount := 0;
RxChars := 0;
ExitFlag := FALSE;
repeat
(* does user want to quit ? *)
if UserQuits(Port) then exit;
(* check receive queue size *)
CheckQueue(Port,LoMark,HiMark);
(* get next character *)
if RxChars = 0 then
begin
(* wait 1 minute for 1st character *)
Code := GetChar(Port,60*ONE_SECOND);
LastTime := SioTimer
end
else Code := GetChar(Port,TimeOut*ONE_SECOND);
(* did we timeout ? *)
if Code = -1 then
begin
(* we have timed out ! *)
ExitFlag := TRUE;
WriteMsg('Ascii: Timeout.');
end;
(* termination character ? *)
if (Code <> -1) and (TermChar<>$00) and (Code=TermChar) then
begin
(* received termination character *)
ExitFlag := TRUE;
WriteMsg('Ascii: Termination character received');
end
else
begin
RxChars := RxChars + 1;
if EchoFlag then write(chr(Code));
if (RxChars mod 100) = 0 then ReportBytes(RxChars);
(* put character in buffer *)
Buffer[DataCount] := Code;
DataCount := DataCount + 1;
if DataCount = 1024 then
begin
if not fioWrite(Buffer,DataCount) then
begin
DiskError;
RxAscii := False;
exit
end;
DataCount := 0;
end
end
until ExitFlag;
(* flush the data buffer *)
if DataCount > 0 then if not fioWrite(Buffer,DataCount) then
begin
DiskError;
RxAscii := False;
exit
end;
(* close the output file *)
fioClose;
RxAscii := True
end; (* end - RxAscii *)
end.